package eduware.dozent;

import java.util.HashMap;

import eduware.ctrl.Ctrl;
import eduware.util.Config;
import eduware.util.WritesConfig;

/***
 * storage for predefined profiles
 * 
 * @author Maik
 * 
 */

public class PredefinedDozentProfiles implements WritesConfig {

	/****************************
	 * storage for the lecturer profile
	 */
	private DozentProfile dozent;

	/****************************
	 * internal storage for the alignment values and the dozentID
	 */
	private int crankiness, friendliness, normalization, dozentID;

	/****************************
	 * constructor to connect the class with the config
	 */
	public PredefinedDozentProfiles() {

		Config.getInstance().registerImplementedInterface(this);

	}

	/****************************
	 * function to calculate and return a certain dozent
	 * 
	 * @param id
	 *            internal lecturer id
	 * @return object containing the generated lecturer
	 */
	public DozentProfile getProfile(int id) {
		dozentID = id;

		/**************************************************************
		 * check for the dozent id and assign all values accordingly
		 */

		if (id == 1) {
			dozent = new DozentProfile();

			dozent.setTooManyQuestionsThreshold(adjustProfileRev(2, 10,
					friendliness));
			dozent.setTooManyQuestionsRememberPeriod(adjustProfileRev(3 * 60,
					30 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyQuestionsMoodDelta(-1
					* adjustProfileRev(1, 5, crankiness));
			dozent.setTooManyQuestionsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSameQuestionThreshold(adjustProfileRev(1, 3, crankiness));
			dozent.setSameQuestionRememberPeriod(adjustProfileRev(5 * 60,
					30 * 60, (int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setSameQuestionMoodDelta(-1
					* adjustProfileRev(1, 4, crankiness));
			dozent.setSameQuestionMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSmallMealsThreshold(adjustProfile(2, 5,
					(int) ((crankiness * 0.75) + (normalization * 0.25))));
			dozent.setSmallMealsRememberPeriod(adjustProfileRev(50 * 60,
					70 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setSmallMealsMoodDelta(-1
					* adjustProfileRev(2, 6, crankiness));
			dozent.setSmallMealsMoodDeltaAdaption(adjustProfileRev(1, 4,
					crankiness));

			dozent.setMediumMealsThreshold(adjustProfile(1, 5,
					(int) ((crankiness * 0.75) + (normalization * 0.25))));
			dozent.setMediumMealsRememberPeriod(adjustProfileRev(90 * 60,
					120 * 60,
					(int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setMediumMealsMoodDelta(-1
					* adjustProfileRev(3, 8, crankiness));
			dozent.setMediumMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setLargeMealsThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.7) + (normalization * 0.3))));
			dozent.setLargeMealsRememberPeriod(adjustProfileRev(130 * 60,
					180 * 60,
					(int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setLargeMealsMoodDelta(-1
					* adjustProfileRev(5, 14, crankiness));
			dozent.setLargeMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setTooManyMealsThreshold(adjustProfile(2, 6, crankiness));
			dozent.setTooManyMealsRememberPeriod(adjustProfileRev(6 * 60,
					20 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyMealsMoodDelta(-1
					* adjustProfileRev(3, 10, crankiness));
			dozent.setTooManyMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSmallDrinksThreshold(adjustProfile(2, 6,
					(int) ((crankiness * 0.75) + (friendliness * 0.25))));
			dozent.setSmallDrinksRememberPeriod(adjustProfileRev(15 * 60,
					30 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setSmallDrinksMoodDelta(-1
					* adjustProfileRev(2, 6, crankiness));
			dozent.setSmallDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setMediumDrinksThreshold(adjustProfile(1, 4,
					(int) ((crankiness * 0.8) + (friendliness * 0.2))));
			dozent.setMediumDrinksRememberPeriod(adjustProfileRev(30 * 60,
					90 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setMediumDrinksMoodDelta(-1
					* adjustProfileRev(4, 9, crankiness));
			dozent.setMediumDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setLargeDrinksThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.65) + (normalization * 0.35))));
			dozent.setLargeDrinksRememberPeriod(adjustProfileRev(60 * 60,
					180 * 60,
					(int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setLargeDrinksMoodDelta(-1
					* adjustProfileRev(5, 10, crankiness));
			dozent.setLargeDrinksMoodDeltaAdaption(adjustProfileRev(1, 4,
					crankiness));

			dozent.setTooManyDrinksThreshold(adjustProfile(1, 6, crankiness));
			dozent.setTooManyDrinksRememberPeriod(adjustProfileRev(6 * 60,
					20 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyDrinksMoodDelta(-1
					* adjustProfileRev(3, 10, crankiness));
			dozent.setTooManyDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setHungerRate(1.3f);
			dozent.setThirstRate(1.1f);
			dozent.setToiletRate(0.9f);
			dozent.setSleepRate(adjustProfileRev(0.9f, 1.1f, crankiness));
			dozent.setMoodRate(adjustProfileRev(
					0.7f,
					1.2f,
					(int) ((crankiness * 0.1) + (friendliness * 0.15) + (normalization * 0.75))));

			dozent.setName("Hans");

			int[] timeFrame = { 360, 600, 720, 900, 1080, 1200, 1320 };
			float[] ratios = { 0.2f, 0.8f, 1.2f, 0.9f, 1.0f, 1.2f, 0.7f, 0.3f };
			dozent.setTdb(new eduware.ctrl.TimeDependantBehavior(timeFrame,
					ratios));

		} else if (id == 2) {
			dozent = new DozentProfile();

			dozent.setTooManyQuestionsThreshold(adjustProfileRev(2, 8,
					(int) ((friendliness * 0.6) + (crankiness * 0.4))));
			dozent.setTooManyQuestionsRememberPeriod(adjustProfileRev(8 * 60,
					30 * 60, (int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setTooManyQuestionsMoodDelta(-1
					* adjustProfileRev(1, 5, crankiness));
			dozent.setTooManyQuestionsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSameQuestionThreshold(adjustProfileRev(1, 3, crankiness));
			dozent.setSameQuestionRememberPeriod(adjustProfileRev(10 * 60,
					40 * 60, (int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setSameQuestionMoodDelta(-1
					* adjustProfileRev(1, 6, crankiness));
			dozent.setSameQuestionMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSmallMealsThreshold(adjustProfile(1, 4,
					(int) ((crankiness * 0.75) + (normalization * 0.25))));
			dozent.setSmallMealsRememberPeriod(adjustProfileRev(20 * 60,
					40 * 60, (int) ((normalization * 0.8) + (crankiness * 0.2))));
			dozent.setSmallMealsMoodDelta(-1
					* adjustProfileRev(3, 7, crankiness));
			dozent.setSmallMealsMoodDeltaAdaption(adjustProfileRev(1, 4,
					crankiness));

			dozent.setMediumMealsThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.75) + (normalization * 0.25))));
			dozent.setMediumMealsRememberPeriod(adjustProfileRev(30 * 60,
					80 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));

			// EASTEREGG: TOO MUCH LARGE MEALS WILL INCREASE MOOD - FAT GUY -
			// ISN'T IT?
			dozent.setMediumMealsMoodDelta(adjustProfileRev(4, 8, crankiness));
			dozent.setMediumMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setLargeMealsThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.8) + (normalization * 0.2))));
			dozent.setLargeMealsRememberPeriod(adjustProfileRev(60 * 60,
					120 * 60,
					(int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setLargeMealsMoodDelta(-1
					* adjustProfileRev(5, 13, crankiness));
			dozent.setLargeMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setTooManyMealsThreshold(adjustProfile(1, 6, crankiness));
			dozent.setTooManyMealsRememberPeriod(adjustProfileRev(6 * 60,
					10 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyMealsMoodDelta(-1
					* adjustProfileRev(5, 10, crankiness));
			dozent.setTooManyMealsMoodDeltaAdaption(adjustProfileRev(1, 4,
					crankiness));

			dozent.setSmallDrinksThreshold(adjustProfile(2, 5,
					(int) ((crankiness * 0.75) + (friendliness * 0.25))));
			dozent.setSmallDrinksRememberPeriod(adjustProfileRev(10 * 60,
					30 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setSmallDrinksMoodDelta(-1
					* adjustProfileRev(2, 6, crankiness));
			dozent.setSmallDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setMediumDrinksThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.8) + (friendliness * 0.2))));
			dozent.setMediumDrinksRememberPeriod(adjustProfileRev(20 * 60,
					50 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setMediumDrinksMoodDelta(-1
					* adjustProfileRev(4, 8, crankiness));
			dozent.setMediumDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setLargeDrinksThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.65) + (normalization * 0.35))));
			dozent.setLargeDrinksRememberPeriod(adjustProfileRev(60 * 60,
					100 * 60,
					(int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setLargeDrinksMoodDelta(-1
					* adjustProfileRev(5, 10, crankiness));
			dozent.setLargeDrinksMoodDeltaAdaption(adjustProfileRev(1, 4,
					crankiness));

			dozent.setTooManyDrinksThreshold(adjustProfile(1, 4, crankiness));
			dozent.setTooManyDrinksRememberPeriod(adjustProfileRev(6 * 60,
					20 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyDrinksMoodDelta(-1
					* adjustProfileRev(3, 10, crankiness));
			dozent.setTooManyDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setHungerRate(1.2f);
			dozent.setThirstRate(1.0f);
			dozent.setToiletRate(1.0f);
			dozent.setSleepRate(adjustProfileRev(1.1f, 1.4f, crankiness));
			dozent.setMoodRate(adjustProfileRev(
					0.9f,
					1.5f,
					(int) ((crankiness * 0.1) + (friendliness * 0.15) + (normalization * 0.75))));

			dozent.setName("Klaus");

			int[] timeFrame = { 420, 600, 750, 870, 1020, 1140, 1200, 1320 };
			float[] ratios = { 0.2f, 0.9f, 1.25f, 1.0f, 1.1f, 1.2f, 1.1f, 0.8f,
					0.3f };
			dozent.setTdb(new eduware.ctrl.TimeDependantBehavior(timeFrame,
					ratios));
		}

		else {

			/***************
			 * HEINZ
			 */

			dozent = new DozentProfile();

			dozent.setTooManyQuestionsThreshold(adjustProfileRev(5, 15,
					friendliness));
			dozent.setTooManyQuestionsRememberPeriod(adjustProfileRev(10 * 60,
					60 * 60, (int) ((normalization * 0.8) + (crankiness * 0.2))));
			dozent.setTooManyQuestionsMoodDelta(-1
					* adjustProfileRev(1, 8, crankiness));
			dozent.setTooManyQuestionsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSameQuestionThreshold(adjustProfileRev(1, 4, crankiness));
			dozent.setSameQuestionRememberPeriod(adjustProfileRev(5 * 60,
					30 * 60, (int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setSameQuestionMoodDelta(-1
					* adjustProfileRev(1, 5, crankiness));
			dozent.setSameQuestionMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSmallMealsThreshold(adjustProfile(2, 5,
					(int) ((crankiness * 0.75) + (normalization * 0.25))));
			dozent.setSmallMealsRememberPeriod(adjustProfileRev(30 * 60,
					120 * 60,
					(int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setSmallMealsMoodDelta(-1
					* adjustProfileRev(3, 7, crankiness));
			dozent.setSmallMealsMoodDeltaAdaption(adjustProfileRev(1, 4,
					crankiness));

			dozent.setMediumMealsThreshold(adjustProfile(1, 4,
					(int) ((crankiness * 0.75) + (normalization * 0.25))));
			dozent.setMediumMealsRememberPeriod(adjustProfileRev(90 * 60,
					120 * 60,
					(int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setMediumMealsMoodDelta(-1
					* adjustProfileRev(3, 10, crankiness));
			dozent.setMediumMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setLargeMealsThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.7) + (normalization * 0.3))));
			dozent.setLargeMealsRememberPeriod(adjustProfileRev(130 * 60,
					180 * 60,
					(int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setLargeMealsMoodDelta(-1
					* adjustProfileRev(6, 14, crankiness));
			dozent.setLargeMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setTooManyMealsThreshold(adjustProfile(1, 5, crankiness));
			dozent.setTooManyMealsRememberPeriod(adjustProfileRev(10 * 60,
					20 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyMealsMoodDelta(-1
					* adjustProfileRev(3, 8, crankiness));
			dozent.setTooManyMealsMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setSmallDrinksThreshold(adjustProfile(2, 6,
					(int) ((crankiness * 0.75) + (friendliness * 0.25))));
			dozent.setSmallDrinksRememberPeriod(adjustProfileRev(15 * 60,
					30 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setSmallDrinksMoodDelta(-1
					* adjustProfileRev(2, 8, crankiness));
			dozent.setSmallDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setMediumDrinksThreshold(adjustProfile(1, 5,
					(int) ((crankiness * 0.8) + (friendliness * 0.2))));
			dozent.setMediumDrinksRememberPeriod(adjustProfileRev(30 * 60,
					90 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setMediumDrinksMoodDelta(-1
					* adjustProfileRev(4, 8, crankiness));
			dozent.setMediumDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setLargeDrinksThreshold(adjustProfile(1, 3,
					(int) ((crankiness * 0.65) + (normalization * 0.35))));
			dozent.setLargeDrinksRememberPeriod(adjustProfileRev(90 * 60,
					120 * 60,
					(int) ((normalization * 0.6) + (crankiness * 0.4))));
			dozent.setLargeDrinksMoodDelta(-1
					* adjustProfileRev(5, 11, crankiness));
			dozent.setLargeDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setTooManyDrinksThreshold(adjustProfile(1, 6, crankiness));
			dozent.setTooManyDrinksRememberPeriod(adjustProfileRev(6 * 60,
					20 * 60, (int) ((normalization * 0.7) + (crankiness * 0.3))));
			dozent.setTooManyDrinksMoodDelta(-1
					* adjustProfileRev(3, 10, crankiness));
			dozent.setTooManyDrinksMoodDeltaAdaption(adjustProfileRev(1, 3,
					crankiness));

			dozent.setHungerRate(1.5f);
			dozent.setThirstRate(1.0f);
			dozent.setToiletRate(1.1f);
			dozent.setSleepRate(adjustProfileRev(0.8f, 1.1f, crankiness));
			dozent.setMoodRate(adjustProfileRev(
					0.7f,
					1.4f,
					(int) ((crankiness * 0.15) + (friendliness * 0.15) + (normalization * 0.7))));

			dozent.setName("Heinz");

			int[] timeFrame = { 360, 600, 720, 900, 1080, 1200, 1320 };
			float[] ratios = { 0.2f, 0.8f, 1.2f, 0.9f, 1.0f, 1.2f, 0.7f, 0.3f };
			dozent.setTdb(new eduware.ctrl.TimeDependantBehavior(timeFrame,
					ratios));

		}
		return dozent;
	}

	public int getCrankiness() {
		return crankiness;
	}

	public void setCrankiness(int crankiness) {
		this.crankiness = crankiness;
	}

	public int getFriendliness() {
		return friendliness;
	}

	public void setFriendliness(int friendliness) {
		this.friendliness = friendliness;
	}

	public int getNormalization() {
		return normalization;
	}

	public void setNormalization(int normalization) {
		this.normalization = normalization;
	}

	public int getDozentID() {
		return dozentID;
	}

	public void setDozentID(int dozentID) {
		this.dozentID = dozentID;
	}

	/***********************************
	 * function to calculate and return a certain dozent
	 * 
	 * @return object containing the defined dozent
	 * @throws Exception
	 *             in case no default dozent has been set
	 */
	public DozentProfile getProfile() throws Exception {
		if (this.dozentID == 0)
			throw new Exception("No default dozent defined");
		return getProfile(this.dozentID);

	}

	/***********************************
	 * function to set the social values of the lecutrer
	 * 
	 * @param crankiness
	 *            value of crankiness between 0 and 10
	 * @param friendliness
	 *            value of friendliness between 0 and 10
	 * @param normalization
	 *            value of normalization between 0 and 10
	 */
	public void setSocialValues(int crankiness, int friendliness,
			int normalization) {
		this.crankiness = crankiness;
		this.friendliness = friendliness;
		this.normalization = normalization;
	}

	/***********************************
	 * function to adjust a certain value based on a social value within a
	 * certain predefined range - the higher the strenth the higher the result
	 * value
	 * 
	 * @param MinVal
	 *            minimum result value
	 * @param MaxVal
	 *            maximum result value
	 * @param Strength
	 *            current strength of the social value (between 0 and 10)
	 * @return returns the calculated value
	 */
	private int adjustProfile(int MinVal, int MaxVal, int Strength) {
		// calculate the according value
		int res = MinVal + (MaxVal - MinVal) * Strength / 10;
		/*
		 * System.out.println("Adjust | Min:" + MinVal + " - Max: " + MaxVal +
		 * " - Strength: " + Strength + "Calculated Value: " + res);
		 */
		return res;
	}

	/***********************************
	 * function to adjust a certain value based on a social value within a
	 * certain predefined range - the higher the strength the higher the result
	 * value
	 * 
	 * @param MinVal
	 *            minimum result value
	 * @param MaxVal
	 *            maximum result value
	 * @param Strength
	 *            current strength of the social value (between 0 and 10)
	 * @return returns the calculated value
	 */
	@SuppressWarnings("unused")
	private float adjustProfile(float MinVal, float MaxVal, int Strength) {
		float res = MinVal + (MaxVal - MinVal) * Strength / 10;
		return res;
	}

	/***********************************
	 * function to adjust a certain value based on a social value within a
	 * certain predefined range - the higher the strenth the lower the result
	 * value
	 * 
	 * @param MinVal
	 *            minimum result value
	 * @param MaxVal
	 *            maximum result value
	 * @param Strength
	 *            current strength of the social value (between 0 and 10)
	 * @return returns the calculated value
	 */
	private int adjustProfileRev(int MinVal, int MaxVal, int Strength) {
		int res = MinVal + (MaxVal - MinVal) * (10 - Strength) / 10;
		System.out.println("AdjustRev | Min:" + MinVal + " - Max: " + MaxVal
				+ " - Strength: " + Strength + "Calculated Value: " + res);
		return res;
	}

	/***********************************
	 * function to adjust a certain value based on a social value within a
	 * certain predefined range - the higher the strenth the lower the result
	 * value
	 * 
	 * @param MinVal
	 *            minimum result value
	 * @param MaxVal
	 *            maximum result value
	 * @param Strength
	 *            current strength of the social value (between 0 and 10)
	 * @return returns the calculated value
	 */
	private float adjustProfileRev(float MinVal, float MaxVal, int Strength) {
		float res = MinVal + (MaxVal - MinVal) * (10 - Strength) / 10;
		return res;
	}

	/******************************
	 * internal function to write the class parameters to the config file
	 */
	@Override
	public void writeConfig(HashMap<String, String> config) {
		config.put("crankiness", "" + this.crankiness);
		config.put("normalization", "" + this.normalization);
		config.put("friendliness", "" + this.friendliness);
		config.put("dozentID", "" + dozentID);
	}

	/*****************************
	 * load the profile settings from the config file
	 */
	public void loadProfile() {
		// loads profile from config file
		this.crankiness = Config.getInstance().getInt("crankiness", 5);
		this.normalization = Config.getInstance().getInt("normalization", 5);
		this.friendliness = Config.getInstance().getInt("friendliness", 5);

		// prevent from cheating :)
		if (this.crankiness + this.normalization + this.friendliness > 15) {
			this.crankiness = 5;
			this.normalization = 5;
			this.friendliness = 5;
		}

		// determine the identifier of the dozent
		this.dozentID = Config.getInstance().getInt("dozentID", 1);

		// set the current dozent in the controller by generating the dozent
		// profile
		Ctrl.getInstance().setDozentProfile(this.getProfile(this.dozentID));

	}
}
